﻿using System;
using System.Web.Mvc;
using System.Web.Routing;
using ManagedUIFlow.Infrastructure.Commands.FlowActionHelpers;
using ManagedUIFlow.Infrastructure.Services;
using ManagedUIFlow.Model;

namespace ManagedUIFlow.Infrastructure.Commands
{
    public class FlowView : ICommand 
    {
        private readonly RequestContext _requestContext;
        private FlowViewServiceBuilder _flowViewServiceBuilder;

        public FlowView(RequestContext requestContext)
        {
            _requestContext = requestContext;
        }
        
        public FlowViewServiceBuilder FlowViewServiceBuilder
        {
            get
            {
                return _flowViewServiceBuilder ?? FlowViewServiceBuilder.Current;
            }
            set { _flowViewServiceBuilder = value; }
        }

        public void Execute(ManagedFlow flow)
        {
            if (flow == null)
                throw new ArgumentNullException("flow");

            var flowViewSerializer = FlowViewServiceBuilder.GetFlowViewService();            
            var key = flowViewSerializer.Serialize(flow, _requestContext);
            if (flow.Redirectable == RedirectBehavior.Auto)
                flowViewSerializer.PostRedirectGet(key, flow, _requestContext);
            var baseFormViewModelType = typeof(FlowViewModel);
            if (flow.ViewData.Model != null)
            {
                // bit of reflection magic and get the types
                //
                var modelType = flow.ViewData.Model.GetType();

                // if the model type is derived from the base type then
                // we can set some properties.
                //
                if (baseFormViewModelType.IsAssignableFrom(modelType))
                    // inject the value to the ViewData.Model property
                    //
                    modelType.GetProperty("Key").SetValue(flow.ViewData.Model, key, null);
            }
            
            flow.ViewData["ExecutionKey"] = key;

            var result = new ViewResult
                             {
                                 ViewName = flow.CurrentNavigation,
                                 //MasterName = ,
                                 ViewData = flow.ViewData,
                                 TempData = flow.TempData
                             };
           
            _requestContext.RouteData.Values["action"] = flow.CurrentNavigation;
            _requestContext.RouteData.Values["controller"] = flow.Name;
            result.ExecuteResult(new EmptyController(_requestContext).ControllerContext);
        }

        class EmptyController : ControllerBase, IDisposable
        {
            public EmptyController(RequestContext context)
            {
                base.Execute(context);
            }

            protected override void ExecuteCore() { }

            public void Dispose()
            {
                Dispose();
            }
        }
    }
}